package its_models.expert_model.expert_help_util;

import database_handler.DatabaseManager;
import help_util.DateTime;
import help_util.IndexConverter;
import its_models.expert_model.ExpertModelProperties;
import java.util.ArrayList;
import model_controller.ControlLayer;
import sudoku_properties.SudokuGameInfoParam;

/************************************************************
 * Class Step Matirx (20090929)
 * 1. Store the next steps to move
 * 2. Store the steps which based on the current puzzle to solve the game
 ************************************************************/

public class StepsMatrix{

    public StepsMatrix(ControlLayer inputController){
        this.Controller = inputController;
        breadthSteps = new ArrayList[LOGICAL_RULES.length];
        for(int i=0; i<this.breadthSteps.length; i++){
            this.breadthSteps[i] = new ArrayList();
        }
        depthSteps = new ArrayList();
        dbManager = new DatabaseManager(inputController);

        // 20091030 phrase2 start
        skillsMatrix = new SkillsMatrix(this.Controller);
        // 20091030 phrase2 end
    }

    public void copy(StepsMatrix stepsMatrix){
        //this.Controller = stepsMatrix.Controller;
        //this.breadthSteps = new ArrayList[LOGICAL_RULES.length];

        for(int i=0; i<this.breadthSteps.length; i++){
            //this.breadthSteps[i] = new ArrayList();
            for(int j=0; j<stepsMatrix.getBreadthStepsFoundOnRule(i).size(); j++){
                StrategyGraphUnit tempUnit = new StrategyGraphUnit();
                tempUnit.copy(stepsMatrix.getBreadthStepsFoundOnRule(i).get(j));

                this.breadthSteps[i].add(tempUnit);
            }
        }

        this.depthSteps = new ArrayList();
        for(int i=0; i<stepsMatrix.getDepthStepsLength(); i++){
            StrategyGraphUnit tempUnit = new StrategyGraphUnit();
            tempUnit.copy(stepsMatrix.getDepthStepsMatrix().get(i));
            this.depthSteps.add(tempUnit);
        }

        this.dbManager = new DatabaseManager(this.Controller);

        // 20091030 phrase2 start
        this.skillsMatrix = new SkillsMatrix(this.Controller);
        // 20091030 phrase2 end
    }

    /* breadthsteps */
    public int getBreadthStepsLength(){
        return breadthSteps.length;
    }

    public ArrayList<StrategyGraphUnit> getBreadthStepsFoundOnRule(int ruleIndex){
        return breadthSteps[ruleIndex];
    }

    public void emptyBreadthSteps(){
        for(int i=0; i<this.breadthSteps.length; i++){
            this.breadthSteps[i].clear();
        }
    }

    /* depthSteps */
    public int getDepthStepsLength(){
        return depthSteps.size();
    }
    public void addDepthSteps(StrategyGraphUnit strategyGraphUnit){

        this.depthSteps.add(strategyGraphUnit);
    }
    public void empthDepthSteps(){
        this.depthSteps.clear();
    }
    public ArrayList<StrategyGraphUnit> getDepthStepsMatrix(){
        return this.depthSteps;
    }
    public void setDepthStepsMatrix(ArrayList<StrategyGraphUnit> inputDepthSteps){
        this.depthSteps = inputDepthSteps;
    }

    /* Both depth and breadth */
    public void recordStepsMatrix(int stepCount){
        
        StringBuffer depthStepsValue = new StringBuffer();
        StringBuffer breadthStepsValue = new StringBuffer();

        for(int i=0; i<depthSteps.size(); i++){
            int index = IndexConverter.getIndex(depthSteps.get(i).getColumnIndex(), depthSteps.get(i).getRowIndex());
            int definiteValue = depthSteps.get(i).getDefiniteValue();
            String logicalRule = depthSteps.get(i).getLogicalRule();
            String scope = depthSteps.get(i).getScopeEffectiveIn();
            String addedSteps = index + CELL_INDEX_VALUE_SEPERATOR + definiteValue + CELL_VALUE_RULE_SEPERATOR
                    + logicalRule + SCOPE_SEPARATOR + scope + STEP_SEPARATOR;
            depthStepsValue.append(addedSteps);
        }

        for(int i=0; i<breadthSteps.length; i++){
            for(int j=0; j<breadthSteps[i].size(); j++){
                int index = IndexConverter.getIndex(breadthSteps[i].get(j).getColumnIndex(), breadthSteps[i].get(j).getRowIndex());
                int definiteValue = breadthSteps[i].get(j).getDefiniteValue();
                String logicalRule = breadthSteps[i].get(j).getLogicalRule();
                /* Record skillsMatrix by means of breadthSteps */
                skillsMatrix.addSkills(breadthSteps[i].get(j).getColumnIndex(), breadthSteps[i].get(j).getRowIndex(), logicalRule);
                //Controller.setTextLearnerStepsMsgBox(logicalRule+"\n");
                String scope = breadthSteps[i].get(j).getScopeEffectiveIn();
                String addedSteps = index + CELL_INDEX_VALUE_SEPERATOR + definiteValue + CELL_VALUE_RULE_SEPERATOR
                        + logicalRule + SCOPE_SEPARATOR + scope+ STEP_SEPARATOR;
                breadthStepsValue.append(addedSteps);
            }
        }
        if(!dbManager.addStepsInStepsMatrix(stepCount, depthStepsValue.toString(), breadthStepsValue.toString())){
            dbManager.recordError(this.getClass().getName().toString(), "Cannot add step ", DateTime.getTimestamp());
        }
    }

    // 20091030 phrase2 start
    public void recordSkillsMatrix(){
        skillsMatrix.recordSkillsMatrix();
    }
    // 20091030 phrase2 end



    /* local variables */
    /* store the breadth of the steps matrix*/
    private ArrayList<StrategyGraphUnit>[] breadthSteps;
    private ArrayList<StrategyGraphUnit> depthSteps;
    /* ControlLayer */
    private ControlLayer Controller;
    private DatabaseManager dbManager;
    /* SkillsMatrix */
    private SkillsMatrix skillsMatrix;

    /* Constants */
    /* SudokuGameInfoParam */
    final static String[] LOGICAL_RULES = SudokuGameInfoParam.getLogicalRules();
    
    /* Srtack value commands & seperators */
    /* Temp */
    final String CELL_INDEX_VALUE_SEPERATOR = ExpertModelProperties.getCellIndexValueSeparator();
    final String CELL_VALUE_RULE_SEPERATOR = ExpertModelProperties.getCellValueRuleSeparator();
    final String STEP_SEPARATOR = ExpertModelProperties.getStepSeparator();
    final String SCOPE_SEPARATOR = ExpertModelProperties.getScopeSeparator();
}